/* $RCSFile: SiteMapManager.ascx.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/AddonNice/PageModules/SiteMap/SiteMapManager.ascx.cs $
 * $log$
 * Revision 20 2010/08/09 10:51:22  christian.surieux
 *   Added Log comment to all .aspx .ascx .master files
 * Revision 19 2010/08/09 09:44:00  christian.surieux
 *   Added Log to cs sources files
 * Revision 6 2010/08/06 19:56:26  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;

using AddonNice.Diagnostics;
using AddonNice.Core;
using AddonNice.Design;
using AddonNice.Helpers;
using AddonNice.Configuration;
using AddonNice.Settings;
using AddonNice.Settings.Cache;
using AddonNice.UI.DataTypes;
using AddonNice.UI.WebControls;

using Telerik.Web.UI;

using Trace2 =  System.Diagnostics.Trace;

namespace AddonNice.PageModules.SiteMap 
{
        
 	#region Local TraceSwitch 
	public class SiteMapManagerTrace : ADNTraceSwitch
	{
		static public ADNTraceSwitch	Sw	=	new ADNTraceSwitch("SiteMapManagerTrace","Special Trace Switch for SiteMap Manager");
	}
	#endregion Local TraceSwitch 

    public partial class SiteMapManager : PortalModuleControl
    {
        PagesDB pagesDB		        =   new PagesDB();
        const string strPageMenu    =   "PageMenu";

        #region Global module implementation

		public override bool AdminModule
		{
			get
			{
				return true;
			}
		}

        public override Guid GuidID 
        {
            get
            {
				return new Guid("{929BDE71-8172-4401-AFDA-194F902CE716}");
			}
        }

        #endregion Global module implementation

        #region Ctor

        public SiteMapManager()
		{
		}
        
        #endregion Ctor

		private void Page_Load(object sender, EventArgs e) 
        {
			if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager Page_Load IsPostBack: {0}",Page.IsPostBack),ModuleTraceSwitch.Sw.Info);
            // If this is the first visit to the page, bind the tab data to the page treeview
            if (!Page.IsPostBack) 
            {
                previewBtn.OnClientClick    =    GetPopupCommand();
                previewBtn.Attributes.Add("href",PortalUrl());
                BuildTreeView1();
                BuildTreeView2();
            }
			if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager Page_Load END.",ModuleTraceSwitch.Sw.Info);
        }

        #region Build Treeviews

        internal class sortNode
        {
            public int parentId;
            public RadTreeNode nd;
        }

        private void BuildTreeView1()
        {
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( "[V]SiteMapManager BuildTreeView1 BEG",SiteMapManagerTrace.Sw.Info);
            //read pages from DB
            SqlDataReader dr                =   null;
            try
            {
                dr                          =   pagesDB.GetAllPortalPages(PortalID);
                string strRoot              =   LocalizeHelper.Localize("SITEMAP_ROOT","Root");
                RadTreeNode root            =   new RadTreeNode(strRoot, "0");
                root.Expanded               =   true;
                RadTree1.Nodes.Add(root);
                Hashtable skTb              =   portalSettings.GetSkinImageMenu(true);
                bool isForm                 =   (Config.AuthenticationMode == System.Web.Configuration.AuthenticationMode.Forms );
                List<sortNode> parenNFnd    =   new List<sortNode>();
                while (dr.Read())
                {
                    // Filter on Page flags
                    if ( dr[StStr.DBPageLayout] != DBNull.Value )
                    {
                        ADNPageFlags Flags  = (ADNPageFlags)dr[StStr.DBPageLayout];
                        /*
                        if ( (Flags & ADNPageFlags.NotOkForMenu) == ADNPageFlags.NotOkForMenu )
                            continue;
                         */
                        if ( !isForm && ( (Flags & ADNPageFlags.OnlyFormsAuthentication) == ADNPageFlags.OnlyFormsAuthentication ) )
                            continue;
                    }
                    int tabId               =   (int)dr[StStr.DBPageID];
                    int parentTabId         =   Convert.IsDBNull(dr[StStr.DBParentPageID]) ? 0 : (int)dr[StStr.DBParentPageID];
                    bool hasModules         =   ((int)dr[StStr.DBPageNbModules]) != 0;
                    RadTreeNode nd          =   new RadTreeNode(string.Format("{0}-{1}",tabId,(string)dr[StStr.DBPageName]), tabId.ToString());
                    RadTreeNode nd1         =   RadTree1.FindNodeByValue(parentTabId.ToString());
                    if (SiteMapManagerTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView1 Adding Node Value: {0}, Text: {1}",nd.Value,nd.Text),SiteMapManagerTrace.Sw.Info);
                    // Store the skin to use in a node attribute to use it after any move
                    string wSkinID          =   ((string)dr[StStr.DBPageSkin]).ToLower().Trim();
                    bool okSkin             =   (skTb[wSkinID] != null);
                    if (okSkin)
                    {
                        nd.Attributes["Skin"]   =   (string)skTb[wSkinID];
                    }
                    else
                    {
                        nd.Attributes["Skin"]   =   (string)skTb["defaultskin"];
                    }
                    // when parent is root display image before name
                    if (nd1 == root)
                    {
                        nd.ImageUrl         =   nd.Attributes["Skin"];
                        if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView1 nd.ImageUrl: {0}", nd.ImageUrl),SiteMapManagerTrace.Sw.Info);
                    }
                    if (nd1 != null)
                    {
                        if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView1 Adding {0} to {1}", nd.Text, nd1.Text),SiteMapManagerTrace.Sw.Info);
                        nd1.Nodes.Add(nd);
                    }
                    else
                    {
                        if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalPagesManager BuildTreeView1 parent not readen nd:{0}, parentTabId: {1}.", nd.Text, parentTabId),SiteMapManagerTrace.Sw.Info);
                        parenNFnd.Add(new sortNode() { parentId = parentTabId,nd = nd });
                        //root.Nodes.Add(nd);
                    }
                    // We check for children already readen
                    for ( int i=0 ; i < parenNFnd.Count ; i++ )
                    {
                        sortNode sn =   parenNFnd[i];
                        if ( sn.parentId == tabId )
                        {
                            if (SiteMapManagerTrace.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalPagesManager BuildTreeView1 child node found nd:{0}, child: {1}.", nd.Text, sn.nd.Text),SiteMapManagerTrace.Sw.Info);
                            nd.Nodes.Add(sn.nd);
                            parenNFnd.RemoveAt(i);
                            i--;
                        }
                    }
                    
                }
                
                // Add the not found nodes to root
                for ( int i=0 ; i < parenNFnd.Count ; i++ )
                {
                    sortNode sn =   parenNFnd[i];
                    if (SiteMapManagerTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalPagesManager BuildTreeView1 node without parent added to root nd:{0}, parentId: {1}.", sn.nd.Text, sn.parentId),SiteMapManagerTrace.Sw.Info);
                    root.Nodes.Add(sn.nd);
                }
                // Remove Admin Node
                RadTreeNode ndAdmin     =   RadTree1.FindNodeByValue(StStr.strPageAdminID);
                ndAdmin.Owner.Nodes.Remove(ndAdmin);
                if (SiteMapManagerTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( "[V]SiteMapManager BuildTreeView1 END.",SiteMapManagerTrace.Sw.Info);
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]SiteMapManager BuildTreeView1 ex: {0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            finally
            {
                if (dr != null)
                    dr.Close();
            }
        }

        private void BuildTreeView2()
        {
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( "[V]SiteMapManager BuildTreeView2 BEG",SiteMapManagerTrace.Sw.Info);
            // insert context menu
            RadTree2.ContextMenus.Add(CreateContextMenu());
            //read pages from DB
            SqlDataReader dr                =   null;
            try
            {
                dr                          =   pagesDB.GetAllSitePortalPages(PortalID);
                string strRoot              =   LocalizeHelper.Localize("SITEMAP_SITEMAPROOT","SiteRoot");
                RadTreeNode root            =   new RadTreeNode(strRoot, "0");
                root.Expanded               =   true;
                RadTree2.Nodes.Add(root);
                Hashtable skTb              =   portalSettings.GetSkinImageMenu(true);
                root.ContextMenuID          =   strPageMenu;
                bool isForm                 =   (Config.AuthenticationMode == System.Web.Configuration.AuthenticationMode.Forms );
                List<sortNode> parenNFnd    =   new List<sortNode>();
                while (dr.Read())
                {
                    if ( dr[StStr.DBPageLayout] != DBNull.Value )
                    {
                        ADNPageFlags Flags  = (ADNPageFlags)dr[StStr.DBPageLayout];
                        /* if ( (Flags & ADNPageFlags.NotOkForMenu) == ADNPageFlags.NotOkForMenu )
                            continue;
                         */
                        if ( !isForm && ( (Flags & ADNPageFlags.OnlyFormsAuthentication) == ADNPageFlags.OnlyFormsAuthentication ) )
                            continue;
                    }
                    int tabId               =   (int)dr[StStr.DBSitePageID];
                    if ( tabId == 0 )
                        continue;
                    RadTreeNode nd0 = RadTree1.FindNodeByValue(tabId.ToString());
                    if (nd0 != null)
                    {
                        if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView2 removing from RadTree1 Id: {0}",tabId),SiteMapManagerTrace.Sw.Info);
                        if (nd0.Nodes.Count != 0)
                        {
                            for (int i=nd0.Nodes.Count-1; i >=0 ; i--)
                            {
                                RadTreeNode ndc =   nd0.Nodes[i];
                                if (SiteMapManagerTrace.Sw.TraceVerbose)
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView2 removing moving sub node Id: {0}",ndc.Value),SiteMapManagerTrace.Sw.Info);
                                ndc.Owner.Nodes.Remove(ndc);
                                nd0.ParentNode.Nodes.Add(ndc);
                            }
                        }
						nd0.Owner.Nodes.Remove(nd0);
                    }
                    int parentTabId =   Convert.IsDBNull(dr[StStr.DBSiteParentPageID]) ? 0 : (int)dr[StStr.DBSiteParentPageID];
                    bool hasModules =   ((int)dr[StStr.DBPageNbModules]) != 0;
                    RadTreeNode nd  =   new RadTreeNode(string.Format("{0}-{1}",tabId,(string)dr[StStr.DBPageName]), tabId.ToString());
                    nd.ContextMenuID=  strPageMenu;
                    RadTreeNode nd1 =   RadTree2.FindNodeByValue(parentTabId.ToString());
                    if (SiteMapManagerTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView2 Adding Node Value: {0}, Text: {1}",nd.Value,nd.Text),SiteMapManagerTrace.Sw.Info);
                    // Store the skin to use in a node attribute to use it after any move
                    string wSkinID  =   ((string)dr[StStr.DBPageSkin]).ToLower().Trim();
                    bool okSkin     =   (skTb[wSkinID] != null);
                    if (okSkin)
                    {
                        nd.Attributes["Skin"]   =   (string)skTb[wSkinID];
                    }
                    else
                    {
                        nd.Attributes["Skin"]   =   (string)skTb["defaultskin"];
                    }
                    // when parent is root display image before name
                    if (nd1 == root)
                    {
                        nd.ImageUrl =   nd.Attributes["Skin"];
                        if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView2 nd.ImageUrl: {0}", nd.ImageUrl),SiteMapManagerTrace.Sw.Info);
                    }
                    if (nd1 != null)
                    {
                        if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView2 Adding {0} to {1}", nd.Text, nd1.Text),SiteMapManagerTrace.Sw.Info);
                        nd1.Nodes.Add(nd);
                    }
                    else
                    {
                        if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalPagesManager BuildTreeView2 parent not readen nd:{0}, parentTabId: {1}.", nd.Text, parentTabId),SiteMapManagerTrace.Sw.Info);
                        parenNFnd.Add(new sortNode() { parentId = parentTabId,nd = nd });
                        //root.Nodes.Add(nd);
                    }
                    // We check for children already readen
                    for ( int i=0 ; i < parenNFnd.Count ; i++ )
                    {
                        sortNode sn =   parenNFnd[i];
                        if ( sn.parentId == tabId )
                        {
                            if (SiteMapManagerTrace.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalPagesManager BuildTreeView2 child node found nd:{0}, child: {1}.", nd.Text, sn.nd.Text),SiteMapManagerTrace.Sw.Info);
                            nd.Nodes.Add(sn.nd);
                            parenNFnd.RemoveAt(i);
                            i--;
                        }
                    }
                    
                }
                // We need to close before SelectNode
                if (dr != null)
                    dr.Close();
                
                // Add the not found nodes to root
                for ( int i=0 ; i < parenNFnd.Count ; i++ )
                {
                    sortNode sn =   parenNFnd[i];
                    if (SiteMapManagerTrace.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]PortalPagesManager BuildTreeView2 node without parent added to root nd:{0}, parentId: {1}.", sn.nd.Text, sn.parentId),SiteMapManagerTrace.Sw.Info);
                    root.Nodes.Add(sn.nd);
                }
                if (SiteMapManagerTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager BuildTreeView2 END not Found nodes: {0}",parenNFnd.Count),SiteMapManagerTrace.Sw.Info);
                parenNFnd.Clear();
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]SiteMapManager BuildTreeView2 ex: {0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            finally
            {
                if (dr != null)
                    dr.Close();
            }
        }

  		/// <summary>
		/// Create the context menu for treeview
		/// </summary>
		RadTreeViewContextMenu CreateContextMenu()
		{
			RadTreeViewContextMenu cm	= new RadTreeViewContextMenu();
			cm.ID					    = strPageMenu;

			RadMenuItem cmi     =	new RadMenuItem();
			cmi.Value			=	"AddPage";
            cmi.ImageUrl        =   portalSettings.GetImageFromThemeSkins("AddPage");

			cmi.Text			=	LocalizeHelper.Localize("SITEMAP_ADDDUMMYPAGE","Add dummy page");
			cmi.PostBack		=	true;
			cm.Items.Add(cmi);

			cmi					=	new RadMenuItem();
			cmi.Value			=	"DeletePage";
            cmi.ImageUrl        =   portalSettings.GetImageFromThemeSkins("DeleteBtn");
			cmi.Text			=	LocalizeHelper.Localize("AM_CONTEXT_DELETEPAGE","Delete Page");
			cmi.PostBack		=	true;
			cm.Items.Add(cmi);
			return cm;
		}
		
        #endregion Build Treeviews

        /// <summary>
		/// Handler for a right button menu click in treeView
		/// </summary>
        void RadTree2_ContextMenuItemClick(object o, RadTreeViewContextMenuEventArgs e)
        {
			string contextCommand = e.MenuItem.Value;
			
			RadTreeNode currentNode = e.Node;
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree2_NodeContextClick contextCommand: {0}", contextCommand),SiteMapManagerTrace.Sw.Info);

			switch (contextCommand)
			{
				case "AddPage":
					AddPage(currentNode);
					break;
				case "DeletePage":
					DeletePage(currentNode);
					break;
			}
		}

        /// <summary>
        /// Remove page under current node in site map
        /// </summary>
        private void DeletePage(RadTreeNode currentNode)
        {
            currentNode.Owner.Nodes.Remove(currentNode);
            RadTree1.Nodes[0].Nodes.Add(currentNode);
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager DeletePage CurentNode: {0}", currentNode.Value),SiteMapManagerTrace.Sw.Info);
		}

        /// <summary>
        /// Add a new dummy page under current node in site map
        /// </summary>
        private void AddPage(RadTreeNode currentNode)
        {
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager AddPage BEG.",SiteMapManagerTrace.Sw.Info);
            string DBAllUser    =   Config.InternallAllUsersRole;
            string DBAllUser2   =   DBAllUser+";";
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager AddPage authorizedRoles : {0}", DBAllUser2),SiteMapManagerTrace.Sw.Info);

			// Add Page info in the database
			int NewPageID = 0;
            string strNodeDummy =   LocalizeHelper.Localize("SITEMAP_DUMMYPAGE","Dummy Menu Page");
            try
            {
                portalSettings.FlushSkinImageMenuCache();
                NewPageID       =   pagesDB.AddPage(portalSettings.PortalID, Int32.Parse(currentNode.Value), strNodeDummy,StStr.strDefaultSkin, 990000
                    ,3,0,0,0,0,0, DBAllUser2);
                //rename it to include page number
                strNodeDummy    =   string.Format("{0}({1})",strNodeDummy,NewPageID);
                pagesDB.UpdatePageName(NewPageID,strNodeDummy);
                if (SiteMapManagerTrace.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager AddPage Added NewPageId: {0}", NewPageID),SiteMapManagerTrace.Sw.Info);
            }
            catch (Exception exp)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]SiteMapManager AddPage ex: {0}", exp),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            RadTreeNode nd          =   new RadTreeNode(string.Format("{0}-{1}",NewPageID,strNodeDummy), NewPageID.ToString());
            nd.ContextMenuID        =   strPageMenu;
            Hashtable skTb          =   portalSettings.GetSkinImageMenu(true);
            nd.Attributes["Skin"]   =   (string)skTb["seppagesskin"];
            if ( currentNode.ParentNode == null )
                    nd.ImageUrl     =   nd.Attributes["Skin"];
            else    nd.ImageUrl     =   string.Empty;
            currentNode.Nodes.Add(nd);
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager AddPage END Added NewPageId: {0}, CurrentNode: {1}", NewPageID,currentNode.Value),SiteMapManagerTrace.Sw.Info);
		}
        
		/// <summary>
		/// User has edited a page name, we change it
		/// </summary>
        void RadTree1_NodeEdit(object o, RadTreeNodeEditEventArgs e)
        {
			RadTreeNode sourceNode  =   e.Node;
			string ntext            =   e.Text;
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree1_NodeEdit BEG Node.Text:{0}, newtext: {1}", sourceNode.Text,ntext),SiteMapManagerTrace.Sw.Info);
            string searchText       =   string.Format("{0}-",sourceNode.Value);
            int idx                 =   ntext.IndexOf(searchText);
            if (idx != -1)
            {
                ntext               =   ntext.Substring(idx + searchText.Length);
            }
            idx                     =   ntext.IndexOf('-');
            if (idx != -1)
            {
                ntext               =   ntext.Substring(idx + 1);
            }
            string txt              =   string.Format("{0}-{1}",sourceNode.Value,ntext);
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree1_NodeEdit  Text: {0}-{1} changed to: {2}", sourceNode.Text, sourceNode.Value, ntext),SiteMapManagerTrace.Sw.Info);
			try
			{
				pagesDB.UpdatePageName(int.Parse(sourceNode.Value), ntext);
				sourceNode.Text         = txt;
			}
			catch (Exception ex)
			{
				if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]SiteMapManager RadTree1_NodeEdit ex:{0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
			}
		}


        /// <summary>
		/// User has moved a node
		/// </summary>
        void RadTree1_NodeDrop(object o, RadTreeNodeDragDropEventArgs e)
        {
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager RadTree1_NodeDrop BEG.",SiteMapManagerTrace.Sw.Info);
            // Fetch event data 
            RadTreeNode sourceNode		= e.SourceDragNode;
            RadTreeNode destNode		= e.DestDragNode;
			if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree1_NodeDrop  {0}.",sourceNode.Text),SiteMapManagerTrace.Sw.Info);
    
            // node may have been dropped outside treeviews, or on itself
			// we can't move to root (destNode.Parent == null)
			// We don't accept inversing hierarchy
			if (destNode == null || sourceNode.Equals(destNode) || sourceNode.IsAncestorOf(destNode) )
				return;

			RadTreeViewDropPosition d	=	e.DropPosition;

			if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree1_NodeDrop  {0} -{1}- {2}",sourceNode.Text,d,destNode.Text),SiteMapManagerTrace.Sw.Info);
			try
			{
				switch (d)
				{
					case RadTreeViewDropPosition.Above:
						sourceNode.Owner.Nodes.Remove(sourceNode);
						destNode.InsertBefore(sourceNode);
						if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree1_NodeDrop: {0}.", sourceNode.Text),SiteMapManagerTrace.Sw.Info);
						break;
					case RadTreeViewDropPosition.Below:
						sourceNode.Owner.Nodes.Remove(sourceNode);
						destNode.InsertAfter(sourceNode);
						if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree1_NodeDrop: {0}.", sourceNode.Text),SiteMapManagerTrace.Sw.Info);
						break;
					case RadTreeViewDropPosition.Over:
						if (SiteMapManagerTrace.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager RadTree1_NodeDrop: {0}.", sourceNode.Text),SiteMapManagerTrace.Sw.Info);
						sourceNode.Owner.Nodes.Remove(sourceNode);
						destNode.Nodes.Add(sourceNode);
						break;
					default:
						return;
				}
                // Display or not the associated icon
                if (( sourceNode.ParentNode != null ) && (sourceNode.ParentNode.ParentNode == null ) )
                        sourceNode.ImageUrl   =   sourceNode.Attributes["Skin"];
                else    sourceNode.ImageUrl   =   string.Empty;
				// Expand destination node to see result of swap immediately.
                if ( sourceNode.ParentNode != null )
				    sourceNode.ParentNode.ExpandChildNodes();
			}
			catch (Exception ex)
			{
				if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]SiteMapManager RadTree1_NodeDrop ex: {0}", ex),ModuleTraceSwitch.Sw.Info);
			}
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager RadTree1_NodeDrop END.",SiteMapManagerTrace.Sw.Info);
        }

        void SaveNode(RadTreeNode nd)
        {
            foreach(RadTreeNode nod in nd.Nodes)
                SaveNode(nod);
            int Id          =   int.Parse(nd.Value);
            // We don't store root node
            if ( Id == 0 )
                return;
            int parentId    =   (nd.ParentNode == null ) ? 0:int.Parse(nd.ParentNode.Value);
            int order       =   nd.Index;
			if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]SiteMapManager SaveNode Id: {0}, ParentId: {1}, order: {2}", Id,parentId,order),SiteMapManagerTrace.Sw.Info);
            pagesDB.AddSiteMapPage(portalSettings.PortalID,Id,parentId,order);
        }

        
        /// <summary>
        /// Reset: Rebuild the treenodes from DB
        /// </summary>
        void ResetBtn_Click(object sender, ImageClickEventArgs e)
        {
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager ResetBtn_Click BEG.",SiteMapManagerTrace.Sw.Info);
            RadTree1.Nodes.Clear();
            RadTree2.Nodes.Clear();
            BuildTreeView1();
            BuildTreeView2();
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager ResetBtn_Click END.",SiteMapManagerTrace.Sw.Info);
        }

        // To reflect current changes in portal
        void ReloadPortal()
        {
            CurrentCache.RemoveGlobalPagesCacheKey();
            CurrentCache.RemoveAll(StStr.PageNavigationSettings);
            CurrentCache.RemoveAll(StStr.AuthorizedPageStripDetail);
		    portalSettings.ReloadPortal(false);
        }

        /// <summary>
        /// Delete the current Sitemap and insert the new one
        /// </summary>
        void SiteMapManager_ADNUpdateModule(object sender, ModuleEventArgs e)
        {
            if (SiteMapManagerTrace.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager SiteMapManager_ADNUpdateModule BEG.",SiteMapManagerTrace.Sw.Info);
            
			try
			{
				pagesDB.DeleteSiteMap(portalSettings.PortalID);
                foreach (RadTreeNode nd in RadTree2.Nodes)
                {
                    SaveNode(nd);
                }
                // cache must be removed
                ReloadPortal();
			}
			catch (Exception ex)
			{
				if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]SiteMapManager SiteMapManager_ADNUpdateModule ex: {0}", ex),ModuleTraceSwitch.Sw.Info);
				throw;
			}
        }

        #region Std overrides

        public override void Page_PreInit(object sender, EventArgs e)
		{
			if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager Page_PreInit BEG.",ModuleTraceSwitch.Sw.Info);
			base.Page_PreInit(sender, e);
			updateBtn.SkinID	=	"Update_"+Helpers.LocalizeHelper.GetCurrentNeutralCultureName();
            resetBtn.SkinID     =   "Reset_" + Helpers.LocalizeHelper.GetCurrentNeutralCultureName();
            previewBtn.SkinID   =   "Preview_" + Helpers.LocalizeHelper.GetCurrentNeutralCultureName();
			if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager Page_PreInit END.",ModuleTraceSwitch.Sw.Info);
		}
		

        override protected void OnInit(EventArgs e)
		{
			if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager OnInit BEG.",ModuleTraceSwitch.Sw.Info);
			InitializeComponent();
			base.OnInit(e);
			if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine("[V]SiteMapManager OnInit END.",ModuleTraceSwitch.Sw.Info);
		}

        private void InitializeComponent() 
        {
			Load					        +=  new EventHandler(this.Page_Load);
            ADNUpdateModule                 +=  new PortalModuleEventHandler(SiteMapManager_ADNUpdateModule);
            RadTree1.NodeDrop               +=  new RadTreeViewDragDropEventHandler(RadTree1_NodeDrop);
            RadTree1.NodeEdit               +=  new RadTreeViewEditEventHandler(RadTree1_NodeEdit);
            RadTree2.NodeDrop               +=  new RadTreeViewDragDropEventHandler(RadTree1_NodeDrop);
            RadTree2.NodeEdit               +=  new RadTreeViewEditEventHandler(RadTree1_NodeEdit);
            RadTree2.ContextMenuItemClick   +=  new RadTreeViewContextMenuEventHandler(RadTree2_ContextMenuItemClick);      
            resetBtn.Click                  +=  new ImageClickEventHandler(ResetBtn_Click);
		}
		
        #endregion Std overrides

    }
}
